/**
 * @copyright   Kevin
 * @license     LGPL 3.0
 * @author      Kevin
 * @checkout    https://gitee.com/bigearrabbit/KevinQt.git
 * @file        KevinListModel.h
 * @note
 * QML: ListModel
 * C++: QAbstractListModel, not QAbstractItemModel
 *
 */

#ifndef KevinListModel_H
#define KevinListModel_H

#include <QAbstractListModel>

#include "KevinListItem.h"

namespace Kevin {
/**
 * @brief KevinList Model
 *
 */
class ListModel : public QAbstractListModel {
    Q_OBJECT;

public:
    explicit ListModel(QObject* parent = nullptr);

    ~ListModel();

public:
    enum DataRoles {
        TitleRole = Qt::UserRole + 1,
        TypeRole,
        IIDRole,
        IconSourceRole,
        SubTypeRole
    };

public:
    /**
     * @brief append data
     *
     * @param data ListItem data
     * @return int error code
     * @note used for C++
     */
    int append(const ListItem& data);

    /**
     * @brief append QVariantMap
     *
     * @param map map of variant
     * @return int error code
     * @note used for QML
     */
    Q_INVOKABLE int append(const QVariantMap& map);

    /**
     * @brief count
     *
     * @return int
     * @note used for QML
     */
    Q_INVOKABLE int count() const;

    /**
     * @brief get data
     *
     * @param index
     * @param role
     * @return QVariant
     * @note QML use this to get data
     */
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;

    /**
     * @brief debug
     *
     */
    void debug();

    /**
     * @brief get item
     *
     * @param row row of the item
     * @return ListItem&
     */
    inline ListItem& get(int row) {
        assert(row > -1 && row < m_pDataList->count());
        return (*m_pDataList)[ row ];
    };

    /**
     * @brief get item
     *
     * @param row row of the item
     * @return const ListItem&
     */
    inline const ListItem& get(int row) const {
        assert(row > -1 && row < m_pDataList->count());
        return (*m_pDataList)[ row ];
    };

    /**
     * @brief insert
     *
     * @param row row of the item
     * @param data ListItem data
     * @return int error code
     * @note used for C++
     */
    int insert(int row, const ListItem& data);

    /**
     * @brief insert a row by a map
     *
     * @param row row of the item
     * @param data ListItem data
     * @return int error code
     * @note used for QML
     */
    Q_INVOKABLE int insert(int row, const QVariantMap& map);

    // Remove data:
    /**
     * @brief remove
     *
     * @param row row of the item
     * @return void
     * @note used for QML
     */
    Q_INVOKABLE void remove(int row);

    /**
     * @brief rowCount
     *
     * @param parent
     * @return int
     * @note QML use this to get count
     */
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;

    /**
     * @brief set sample
     *
     */
    void sample();

    /**
     * @brief Set the Data object
     *
     * @param index QModelIndex
     * @param value QVariant
     * @param role data role
     * @return true
     * @return false
     */
    bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;

protected: // interface QAbstractListModel
    /**
     * @brief role Names
     *
     * @return QHash<int, QByteArray>
     * @note QML use this to get role Names
     */
    virtual QHash<int, QByteArray> roleNames() const;

private:
    /**
     * @brief your own data list
     *
     */
    QList<ListItem>* m_pDataList;
};
} // namespace Kevin

#endif // KevinListModel_H
